home *** CD-ROM | disk | FTP | other *** search
/ Atari Forever 4 / Atari Forever 4 / Atari Forever 4.iso / SERIE_AI / AI_017 / INTERNET.TOS / SOFTWARE / TUWTCPSR / IP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-23  |  9.2 KB  |  469 lines

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <tos.h>
  5. #include <aes.h>
  6. #include "pktdrv.h"
  7. #include "ip.h"
  8. #include "arp.h"
  9. #include "icmp.h"
  10. #include "netdb.h"
  11. #include "queue.h"
  12. #include "inetcust.h"
  13.  
  14. #include "cookie.h"
  15. #include "nettrace.h"
  16.  
  17. #define Bconws(x) dpy = x;while(*dpy)(Bconout(2,*dpy++))
  18.  
  19. static char *dpy;
  20.  
  21. #define noDEBUG
  22. #define noDEBUGP
  23. #define noDEBUGA
  24. #define noDEBUGPKT
  25. #define noDEBUGF
  26.  
  27. #define AMASK   0x80L
  28. #define AADDR   0x00L
  29. #define BMASK   0xC0L
  30. #define BADDR   0x80L
  31. #define CMASK   0xE0L
  32. #define CADDR   0xC0L
  33.  
  34. #ifdef DEBUGF
  35. static char str[100];
  36. #endif
  37.  
  38. extern long q_disint(void);
  39. extern long q_enabint(void);
  40. extern long p_disint(void);
  41. extern long p_enabint(void);
  42.  
  43. INADDR lcl_inaddr = 0L;            /* my internet address */
  44. INADDR gw_inaddr = 0L;
  45. INADDR lcl_netmask = (-1L);
  46.  
  47. int ip_recv(int,char *);        /* receive handler */
  48. static struct ip_protocol
  49. {
  50.     int        (*handler)(PACKET *,int,INADDR);
  51.     int        (*du_handler)(IP *);
  52.     int        protocol;
  53. } ip_protab[MAXIP];
  54. static int ip_protocols = 0;
  55. static int ip_handle = -1;
  56. PKTQUEUE    *ip_qrecv = NULL;
  57. int ip_freecnt = 0;
  58.  
  59. extern INETCUST *custom;
  60.  
  61. INADDR iproute(INADDR);
  62. INADDR fixup_subnet_mask(INADDR, int);
  63.  
  64.  
  65. INADDR    ip_myaddr()
  66. {
  67.     return(lcl_inaddr);
  68. }
  69.  
  70. int ip_init(void)
  71. {
  72. int        nbuf;
  73. HADDR    gw_haddr;
  74. int     i;
  75.  
  76.  
  77.     lcl_inaddr = custom->inaddr;
  78.     gw_inaddr = custom->gateway;
  79.     if(arp_init() < 0)
  80.     {
  81.         fprintf(stderr,"arp-init failed\n");
  82.         return(FALSE);
  83.     }
  84.     if(gw_inaddr)
  85.     {
  86.         while((i=arp_in2haddr(gw_inaddr,gw_haddr)) == ARP_WAIT)
  87.         {
  88.             net_demux(FALSE,DEMUX);
  89.         }
  90.         if(i==ARP_OK)
  91.         {
  92. #ifdef DEBUG
  93.             printf("arp for gateway succeded\n");
  94. #endif
  95.             arp_addgw(gw_inaddr,gw_haddr);
  96.         }
  97.     }
  98.     if(custom->subnetbits)
  99.         lcl_netmask = fixup_subnet_mask(lcl_inaddr,custom->subnetbits);
  100.     if(ip_handle < 0)    /* first time called, init net */
  101.     {
  102.         ip_handle = net_open(ET_IP,ip_recv);
  103.                                     /* install demux function */
  104.         if(ip_handle < 0) return(FALSE);
  105.         if(!net_demux(TRUE,ip_demux))
  106.         {
  107.             net_release(ET_IP);
  108.             ip_handle=-1;
  109.             return(FALSE);
  110.         }
  111.         icmp_init();
  112.     }
  113.     nbuf = IP_NBUF;
  114.     ip_qrecv = ip_q_create(nbuf,0);
  115.     if(!ip_qrecv) return(FALSE);
  116.     ip_freecnt = nbuf;
  117.     return(TRUE);
  118. }
  119.  
  120. int ip_exit(void)
  121. {
  122.     while(ip_protocols)
  123.     {
  124.         ip_close(ip_protab[0].protocol);
  125.     }
  126.     ip_q_delete(ip_qrecv);
  127.     net_demux(FALSE,ip_demux);    /* uninstall demuxer */
  128.     net_release(ET_IP);
  129.     ip_handle = -1;
  130. #ifdef DEBUG
  131. printf("ip_exit\n");
  132. #endif
  133.     arp_exit();
  134.     return(TRUE);
  135. }
  136.  
  137. int ip_open(int protocol,
  138.             int (*prot_handler)(PACKET *,int,INADDR),
  139.             int (*du_handler)(IP *))
  140. {
  141. register int    i;
  142.  
  143.  
  144.     if(ip_protocols >= MAXIP) return(FALSE);
  145.     for(i=0; i<ip_protocols; i++)
  146.     {
  147.         if(ip_protab[i].protocol == protocol) return(FALSE);
  148.     }
  149.     ip_protab[ip_protocols].protocol = protocol;
  150.     ip_protab[ip_protocols].handler = prot_handler;
  151.     ip_protab[ip_protocols].du_handler = du_handler;
  152.     ip_protocols++;
  153.     return(TRUE);
  154. }
  155.  
  156.  
  157. int ip_close(int protocol)
  158. {
  159. register int i;
  160.     for(i=0; i<ip_protocols; i++)
  161.     {
  162.         if(ip_protab[i].protocol == protocol)
  163.         {
  164.             for(;i<ip_protocols-1;i++)
  165.             {
  166.                 ip_protab[i].protocol = ip_protab[i+1].protocol;
  167.                 ip_protab[i].handler = ip_protab[i+1].handler;
  168.                 ip_protab[i].du_handler = ip_protab[i+1].du_handler;
  169.             }
  170.             ip_protocols--;
  171.             return(TRUE);
  172.         }
  173.     }
  174.     return(FALSE);
  175. }
  176.  
  177.  
  178. int ip_recv(int length,char *pkt)
  179. {
  180. register int q_ok;
  181. void ip_demuxx(void);
  182.  
  183.             /* insert packet into ip receive queue */
  184.     q_ok = ip_aq_putpkt(ip_qrecv,(PACKET *)pkt);
  185.     if(q_ok) ip_demuxx();
  186.     return(q_ok);
  187. }
  188.  
  189. void ip_demuxx(void)
  190. {
  191. extern void pkt_mux(void);
  192.  
  193.      pkt_mux();    
  194. }
  195.  
  196. int ip_demux(void)
  197. {
  198. register PACKET    *pkt;
  199. register IP     *ip;
  200. register u_short    csum;
  201. register int        i;
  202. register int        len;
  203. int loop;
  204.  
  205.   for(loop = 0;loop < 2; loop++)
  206.   {
  207.     pkt = ip_aq_getpkt(ip_qrecv);    /* get packet */
  208.     if(!pkt) return(FALSE);        /* no packet there */
  209.     
  210. #ifdef DEBUG
  211. printf("ip pkt recv ");
  212.  
  213. #endif
  214.  
  215.     ip = ip_head(pkt);
  216.  
  217.     if(ip_version(ip) != IP_VERSION)
  218.     {
  219. #ifdef DEBUG
  220.     printf("bad version\n");
  221. #endif
  222.         ip_free(pkt);        /* bad version */
  223.         return(FALSE);
  224.     }
  225.     csum = ip->chksum;
  226.     ip->chksum = 0;
  227.  
  228.     if(chksum((u_short *)ip, ip_hdrlen(ip),0) != csum ) 
  229.     {
  230. #ifdef DEBUG
  231.     printf("bad chksum\n");
  232. #endif
  233.         ip_free(pkt);        /* bad checksum */
  234.         return(FALSE);
  235.     }
  236.  
  237.     ip->chksum = csum;
  238.     if (ip->dst_inaddr != lcl_inaddr )        /* not for me */
  239.         /*ip->dst_inaddr == 0xFFFFFFFFL)*/        /* or not broadcast */
  240.     {                                        /* packet not for me */
  241. #ifdef DEBUG
  242.     printf("not for me (%lx)\n",ip->dst_inaddr);
  243. #endif
  244.         ip_free(pkt);    /* drop packet */
  245.         return(FALSE);
  246.     }
  247.     if(ip->frag)
  248.     {
  249. #ifdef DEBUG
  250.         printf("ip packet FRAGMENTED\n");
  251. #endif
  252.         ip_free(pkt);    /* drop fragmented packet */
  253.         return(FALSE);
  254.     }
  255.     len = ip->length - ip_hdrlen(ip);
  256. #ifdef DEBUG
  257.     printf("protocol %2d\n",(int)ip->protocol);
  258. #endif
  259.     for(i=0; i < ip_protocols; i++)
  260.     {
  261.         if(ip_protab[i].protocol == (int)ip->protocol)
  262.         {                /* add immediate reply entry */
  263.             arp_add2tab(ip->src_inaddr,pkt->pkt_head.et_src);
  264.             if(ip_protab[i].handler)
  265.             {
  266.                 ip_protab[i].handler(pkt,len,ip->src_inaddr);
  267.                 break;
  268.             }
  269.             else
  270.             {
  271.               ip_free(pkt);
  272.               break;
  273.             }
  274.         }
  275.     }
  276.     if(i >= ip_protocols)
  277.     {
  278.                 /* no one wants packet */
  279.      if(ip->dst_inaddr == lcl_inaddr)
  280.         icmp_dstun(ip->src_inaddr,ip,ICMP_DSTPROT);
  281.  
  282.      ip_free(pkt);
  283.      return (FALSE);
  284.     }
  285.   }
  286.   return TRUE;
  287. }
  288.  
  289.  
  290. PACKET *ip_alloc(int length, int optlen)
  291. {
  292. register PACKET    *pkt;
  293. register IP        *ip;
  294.  
  295.     pkt = (PACKET *)net_pktalloc(ET_IP);
  296.     
  297.     if(!pkt)
  298.     {
  299.         Bconws("couldn't alloc IP packet\r");
  300.         return(NULL);
  301.     }
  302.  
  303.     ip = ip_head(pkt);
  304.  
  305.   /* internet header */
  306.     ip->vh = (IP_VERSION << 4) + IP_HDR + (optlen + 3)/4;
  307.     ip->tos    = IP_TOS;
  308.     ip->ident = 0;
  309.     ip->frag = 0;  /* don't fragment */
  310.     ip->length = length;
  311.     ip->ttl = IP_TTL;
  312.     ip->chksum = 0;
  313.     return(pkt);
  314. }
  315.  
  316. int ip_free(PACKET *pkt)
  317. {
  318. int i;
  319.     i = net_pktfree((char *)pkt);
  320.     if(!i)
  321.     {
  322.         Bconws("couldn't free IP packet\r");
  323.     }
  324.     return(i);
  325. }
  326.  
  327.  
  328. int ip_send(int protocol, PACKET *pkt,int length, INADDR fhost)
  329. {
  330. register IP *ip;
  331. register int i;
  332. #ifdef DEBUG
  333. printf("ip_send %d octets\n",length);
  334. #endif
  335.  
  336. #ifdef DEBUGF
  337. TRACE(">ip_send\n");
  338. #endif
  339.  
  340.  
  341.   ip = ip_head(pkt);    
  342. #ifdef DEBUGF
  343. TRACE("+>ip_send 1\n");
  344. #endif
  345.  
  346.         /* internet header */
  347.     ip->protocol = protocol;
  348.     ip->length = ip_hdrlen(ip) + length;
  349.     ip->chksum = 0;
  350.     ip->dst_inaddr = fhost;
  351.     ip->src_inaddr = lcl_inaddr;
  352.     ip->chksum = chksum((u_short *)ip, ip_hdrlen(ip),0);
  353. #ifdef DEBUGF
  354. TRACE("+>ip_send chksum\n");
  355. #endif
  356.     pkt->pkt_head.et_type = ET_IP;
  357.     net_getadr((int)sizeof(HADDR),pkt->pkt_head.et_src);
  358. #ifdef DEBUGF
  359. TRACE("+>ip_send getadr\n");
  360. #endif
  361.     fhost = iproute(fhost);
  362. #ifdef DEBUGF
  363. TRACE("+>ip_send iproute\n");
  364. #endif
  365.     while((i=arp_in2haddr(fhost,pkt->pkt_head.et_dest)) == ARP_WAIT)
  366.     {
  367.         evnt_timer(10,0);
  368.         net_demux(FALSE,DEMUX);
  369.     }
  370. #ifdef DEBUGF
  371. TRACE("+>ip_send arp done\n");
  372. #endif
  373.     if(i != ARP_OK)
  374.     {
  375. #ifdef DEBUGA
  376.         printf("arp failed\n");
  377. #endif
  378. #ifdef DEBUGF
  379. TRACE("<ip_send, arp failed\n");
  380. #endif
  381.         return(-1);
  382.     }
  383.     i = net_send(ip->length+(int)sizeof(ETH),(char *)pkt);
  384.  
  385. #ifdef DEBUGF
  386. sprintf(str,"<ip_send,ret = %d\n",i);
  387. TRACE(str);
  388. #endif
  389.  
  390.     return(i);
  391. }
  392.  
  393. /* called from ICMP */
  394. int ip_dudemux(IP *ip)
  395. {
  396. int i;
  397.     for(i=0; i<ip_protocols; i++)
  398.     {
  399.         if(ip_protab[i].protocol == (int)ip->protocol)
  400.         {
  401.             if(ip_protab[i].du_handler)
  402.             {
  403.                 ip_protab[i].du_handler(ip);
  404.                 return(TRUE);
  405.             }
  406.         }
  407.     }            /* no one wants packet */
  408.     return(ip != NULL);
  409. }
  410.  
  411. int ip_requeue(PACKET *pkt)
  412. {
  413.     if(ip_freecnt > 2)                /* keep min 2 free packets */
  414.     {
  415.         return(ip_aq_putpkt(ip_qrecv,pkt));    /* put packet again into receive queue */
  416.     }
  417.     return(FALSE);
  418. }
  419.  
  420. INADDR iproute(INADDR fhost)
  421. {
  422. register int i;
  423. #ifdef DEBUGF
  424. TRACE(">ip_route\n");
  425. #endif
  426.  
  427.     /* first check through the redirect table for this host */
  428.     for(i=0; i<REDIRTABLEN && redtab[i].dst_inaddr; i++)
  429.         if(redtab[i].dst_inaddr == fhost) 
  430.         {
  431. #ifdef DEBUGF
  432. TRACE("<ip_route tabentry found\n");
  433. #endif
  434.             return(redtab[i].gw_inaddr);
  435.         }
  436.  
  437.         /* Check if it is on my net */
  438.     if(lcl_netmask == (-1L) || (lcl_inaddr & lcl_netmask) ==
  439.        (fhost & lcl_netmask))
  440.     {
  441. #ifdef DEBUGF
  442. TRACE("<ip_route mask fit\n");
  443. #endif
  444.         return(fhost);
  445.     }
  446.  
  447.     if((fhost == 0xffffffffL))    /* broadcast */
  448.     {
  449. #ifdef DEBUGF
  450. TRACE("<ip_route broadcast\n");
  451. #endif
  452.         return(fhost);
  453.     }
  454.  
  455.     /* The host isn't on a net I'm on, 
  456.         so send it to the default gateway
  457.     */
  458.  
  459.     if(!gw_inaddr)
  460.     {
  461. #ifdef DEBUGF
  462. TRACE("<ip_route no gateway\n");
  463. #endif
  464.         return(fhost);
  465.     }
  466.     
  467. #ifdef DEBUGF
  468. TRACE("<ip_route gateway\n");
  469. #endif
  470.  
  471.     return(gw_inaddr);
  472. }
  473.  
  474.  
  475. /* Fix the subnet mask given the IP address and the number of subnet bits.
  476. */
  477. INADDR fixup_subnet_mask(INADDR lcl_inaddr, int subnet_bits) 
  478. {
  479. INADDR smask;
  480.  
  481.         /* initialize the bit field */
  482.     if((lcl_inaddr & AMASK) == AADDR)
  483.         smask = 0xFF000000L;
  484.     else if((lcl_inaddr & BMASK) == BADDR)
  485.         smask = 0xFFFF0000L;
  486.     else if((lcl_inaddr & CMASK) == CADDR)
  487.         smask = 0xFFFFFF00L;
  488.  
  489.     while(subnet_bits--)
  490.         smask = (smask >> 1) | 0x80000000L;
  491.     return(smask);
  492. }
  493.